﻿<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0066)http://www.codeproject.com/script/Articles/ViewHtml.aspx?aid=16955 -->
<HTML xmlns="http://www.w3.org/1999/xhtml"><HEAD><TITLE>CodeProject: Article HTML. Free source code and programming help</TITLE>
<META http-equiv=Content-Type content="text/html; charset=utf-8"><LINK 
href="article_files/CodeProject.css" type=text/css rel=stylesheet>
<META content="MSHTML 6.00.6001.18099" name=GENERATOR></HEAD>
<BODY><!--  HTML for article "SvnPerms dot Net" by Riaan Lehmkuhl\nURL: http://www.codeproject.com/KB/cs/SvnPermsNet.aspx
Copyright 2006 by Riaan Lehmkuhl\nAll formatting, additions and  alterations Copyright © CodeProject, 1999-2008 -->
<P><B>Please choose 'View Source' in your browser to view the HTML, or File | 
Save to save this file to your hard drive for editing.</B></P>
<HR class="Divider subdue">

<DIV><SPAN id=ArticleContent>
<UL class=download>
  <LI><A 
  href="http://www.codeproject.com/KB/cs/SvnPermsNet/SvnPermsNet_src.zip">Download 
  source files - 10.7 Kb</A></LI></UL>
<P><IMG height=302 alt="Sample Image - SvnPermsNet.jpg" 
src="article_files/SvnPermsNet1.jpg" width=554></P>
<P><IMG height=302 alt="Sample Image - SvnPermsNet.jpg" 
src="article_files/SvnPermsNet2.jpg" width=554></P>
<H2>Introduction</H2>
<P>I implemented <A href="http://subversion.tigris.org/" 
target=_blank>Subversion</A> on windows to use Active Directory Authentication. 
I could not get the <A 
href="http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/svnperms.py" 
target=_blank><EM>svnperms.py</EM></A> hook script to function correctly, 
however, and I've been looking for an excuse to try out .NET Framework 2.0. So 
here it is: <EM>SvnPerms.net</EM>. </P>
<P><EM>SvnPerms.net</EM> is a C# port of the <A 
href="http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/svnperms.py" 
target=_blank><EM>svnperms.py</EM></A> hook script supplied with <A 
href="http://subversion.tigris.org/" target=_blank>Subversion</A>. The only 
feature I've added is log message validation. This article assumes that you are 
familliar with SVN.</P>
<P>Check out a <A href="http://svnpermsdotnet.googlecode.com/svn/trunk/">working 
copy</A> using <A href="http://tortoisesvn.tigris.org/" 
target=_blank>TortoiseSVN</A>. </P>
<H2>System requirements</H2>
<OL>
  <LI><A href="http://subversion.tigris.org/" target=_blank>SVN command line 
  client</A> 
  <LI><A href="http://msdn2.microsoft.com/en-us/netframework/aa731542.aspx" 
  target=_blank>.NET Framework 2.0</A> </LI></OL>
<H2>The components</H2>
<OL>
  <LI><A 
  href="http://www.codeproject.com/KB/cs/#config"><EM>svnperms.xml</EM></A> 
  <LI><A 
  href="http://www.codeproject.com/KB/cs/#svnperms"><EM>SvnPerms.exe</EM></A> 
  <LI><A 
  href="http://www.codeproject.com/KB/cs/#hook"><EM>pre-commit.bat</EM></A> 
</LI></OL><A name=config>
<H3>svnperms.xml</H3></A>
<P>The configuration file:</P><PRE lang=xml>&lt;svnperms&gt;
    &lt;settings&gt;
        &lt;setting name="SvnDir"&gt;C:\svn\bin&lt;/setting&gt;
        &lt;setting name="LogRegex"&gt;[a-zA-Z0-9]&lt;/setting&gt;
        &lt;setting name="LogRegexMsg"&gt;You failed to supply a valid log message.&lt;/setting&gt;
        &lt;setting name="ErrMsgSuffix"&gt;Please contact your SVN admin.&lt;/setting&gt;
    &lt;/settings&gt;
    &lt;groups&gt;
        &lt;group1&gt;dev1,dev2,dev3&lt;/group1&gt;
        &lt;group2&gt;dev4,dev5&lt;/group2&gt;
    &lt;/groups&gt;
    &lt;sections&gt;
        &lt;default repos="repo1,repo2"&gt;
            &lt;location path
                ="^\btrunk\b\/.*" actions
                ="add,remove,update"&gt;@group1,dev4&lt;/location&gt;
            &lt;location path
                ="^\btags\b\/\w+\/" actions
                ="add"&gt;@group1,dev4&lt;/location&gt;
            &lt;location path
                ="^\bbranches\b\/\w+\/" actions
                ="add,remove,update"&gt;@group1,@group2&lt;/location&gt;
            &lt;location path
                =".*" actions
                ="add,remove,update"&gt;svnadministrator0&lt;/location&gt;
        &lt;/default&gt;
        &lt;repo4&gt;
            &lt;location path=".*" actions="add,remove,update"&gt;*&lt;/location&gt;
        &lt;/repo4&gt;
    &lt;/sections&gt;
&lt;/svnperms&gt;
</PRE>
<OL>
  <LI>The <CODE>setting[@name='SvnDir']</CODE> element: the path to the SVN 
  command line client. 
  <LI>The <CODE>setting[@name='LogRegex']</CODE> element: regex to validate log 
  messages. 
  <LI>The <CODE>groups</CODE> element: groups of users. 
  <LI>The <CODE>sections</CODE> element: repos to match. 
  <UL>
    <LI>The <CODE lang=text>default</CODE> section allows for repos that all 
    have the same structure, e.g. trunk, branches and tags. 
    <LI>Repos with other structures can be defined with more sections. 
  </LI></UL>The sections consist of <CODE>location</CODE> elements -- each with 
  a change <CODE>path</CODE> regex attribute -- and an <CODE>actions</CODE> 
  attribute containing "add," "remove" and "update" or any combination of the 
  three. The text of the <CODE>location</CODE> element contains a 
  comma-separated list of groups and users. </LI></OL><A name=svnperms>
<H3>SvnPerms.exe</H3></A>
<P>Calling <EM>SvnPerms.exe</EM> with no arguments:</P><PRE>$&gt;SvnPerms.exe
USAGE: SvnPerms TXN|REV REPOS [ CONF ] [ -r ]
      TXN     Query transaction TXN for commit information.
      REPOS   Use repository at REPOS to check transactions.
      CONF    Config file path;
              defaults to 'svnperms.xml' in application directory.

      -r      Debug mode:
              Uses revision number instead of commit transaction nubmer.
Author: Riaan Lehmkuhl 2006.</PRE>
<P>Calling the SVN commands:</P><PRE lang=cs>        private static string SvnCmd(string cmd) {
            string fileName = string.Empty;
            string arguments = string.Empty;
            
            // build Svn command.

            switch (cmd.ToLower()) {
                case "changed" :
                case "author" :
                case "log" :
                    fileName = string.Concat(_svnDir, "svnlook");
                    arguments = string.Concat(" ", cmd, " ", _switch, 
                        " \"", _txnRev, "\" \"", _repos, "\"");
                    break;
                default :
                    _stdOut = null;
                    _stdErr = "Svn Command '" + cmd + "' not supported.";
                    return _stdOut;
            }
            
            // call svn command.

            System.Diagnostics.Process process 
                = new System.Diagnostics.Process();
            process.StartInfo.FileName = fileName;
            process.StartInfo.Arguments = arguments;
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardError = true;
            process.StartInfo.CreateNoWindow = true;
            process.Start();
            process.WaitForExit();
            
            // read the output.

            _stdErr = process.StandardError.ReadToEnd();
            _stdOut = process.StandardOutput.ReadToEnd();
            
            return _stdOut;
        }</PRE>
<P>I've tried to comment the code as much as I had time for, to explain how the 
application fits together. When the log has been validated sucessfuly and the 
user has the required permissions, <EM>SvnPerms.exe</EM> will exit with an exit 
code of 0. Otherwise, it will exit with a non-zero exit code that will cancel 
and rollback the commit.</P><A name=hook>
<H3>pre-commit.bat</H3></A><PRE>SET REPOS=%1
SET REV=%2

[drive]:\[path]\SvnPerms.exe %REV% %REPOS%</PRE>
<P>Modify the path to where you have put <EM>SvnPerms.exe</EM>. Copy the 
<EM>pre-commit.bat</EM> file to the repository's "hooks" directory. Any commits 
will be validated by <EM>SvnPerms.exe</EM>.</P>
<H2>History</H2>
<STRONG>16 August 2008</STRONG>
<UL>
  <LI>Upgraded Solution to VS 2008. 
  <LI>Log error message can be configured from config. 
  <LI>Error messages can suffixed by a custom message from config.
  <LI>Some minor bug fixes. </LI></UL>
<P><STRONG>16 May 2007</STRONG></P>
<UL>
  <LI>Updated usage message. 
  <LI>Fixed bug in argument handling. 
  <LI>Ignore empty changes. 
  <LI>Added support for multiple permissions on a repository. </LI></UL>
<P><STRONG>31 Dec 2006</STRONG> </P>
<UL>
  <LI>Original article posted </LI></UL></SPAN></DIV></BODY></HTML>
